import { IPackNifi } from "src/inter";
import Nifi from "src/nifi";

// import { h } from "vue";
import type { Cell,Node } from "pack-antv-x6";
import { getCamelName, trycall } from "../util"
import { ElMessage } from "element-plus";
//
import useConnections from "./connections"
import useProcessors from "./processors"
import useBlank from "./blank"
import useProcessGroups from "./processGroups"
import useFunnels from "./funnels"
import useInputPorts from "./inputPorts"
import useOutputPorts from "./outputPorts"
import useLabels from "./labels"
//
import {t} from "../i18n/index"
//
type CellState = "RUN_ONCE" | "STOPPED" | "RUNNING" | "DISABLED";
//
interface OC {
    data: Map<string, any>
    set: (data: any) => void;
    get: (cell: IPackNifi.SC) => any
    //
    getCellRevision: (cell: IPackNifi.SC) => any
    getCellVersion: (cell: IPackNifi.SC) => number
    //
    getCell: (cell: Cell) => Promise<any>
    delCell: (cell: Cell) => Promise<any>
    addCell: (cell: Cell, data: any) => Promise<any>
    setCell: (cell: Cell, data: any) => Promise<any>
    //
    setCellStatus: (cell: Cell, state: CellState) => Promise<any>;
    //
    handleEdit: () => void
    handleView: () => void
    // modules
    processors: IPackNifi.ModuleProcessors
    connections: IPackNifi.ModuleConnections
    blank: IPackNifi.ModuleBlank
    funnels: IPackNifi.ModuleFunnels
    processGroup: IPackNifi.ModuleProcessGroup
    labels: IPackNifi.ModuleLabels
    outputPorts: IPackNifi.MoudleOutputPorts
    inputPorts: IPackNifi.ModuleInputPorts
    remoteProcessGroup: IPackNifi.ModuleRemoteProcessGroup
}
//
export default (nifi: Nifi): IPackNifi.Cells => {


    // 新建对象
    const c: any = new Object();
    // 原始数据保存
    c.data = new Map<string, any>();
    c.hooks = new Map<string,any>();
    c.set = (td: any) => {c.data.set(td.id, td);c.runHook(td.id,td)}
    c.get = (cell: IPackNifi.SC) => c.data.get(typeof cell == 'string' ? cell : cell.id)
    c.has = (cell: IPackNifi.SC) => c.data.has(typeof cell == 'string' ? cell : cell.id)
    c.del = (cell:IPackNifi.SC) => {
        const id = typeof cell == 'string' ? cell : cell.id ;
        c.data.delete(id);
        c.delHook(id)
    }
    //
    c.addHook = (sid:string,tid:string,f:(d:any) => void) => {
        const d = c.hooks.get(sid) || {};
        d[tid] = f;
        if(!c.hooks.has(sid)){
            c.hooks.set(sid,d)
        }
    }

    c.delHook = (id:string) => {
        c.hooks.delete(id)
    }

    c.runHook = (id:string,d?:any) => {
        const o = c.hooks.get(id) || {};
        const ids = Object.keys(o);
        for(const tid of ids){
            if(c.data.has(tid)){
                const f = o[tid];
                if(typeof f === 'function'){
                    f(d || c.data.get(id),tid)
                }
            }else{
                delete o[tid]
            }
        }
    }
    //
    c.getCellRevision = (cell: IPackNifi.SC) => c.get(cell)?.revision;
    c.getCellVersion = (cell: IPackNifi.SC) => c.getCellRevision(cell)?.version;
    //
    c.getCell = (cell: Cell, message?: string) => trycall(() => nifi.api.get(`/nifi-api/${cell.prop('name')}/${cell.id}`), message);
    c.delCell = (cell: Cell, message?: string) => trycall(() => {
        return nifi.api.delete(`/nifi-api/${cell.prop('name')}/${cell.id}?version=${c.getCellVersion(cell)}`).then(() => {
            nifi.graph.removeCell(cell);
            c.del(cell)
        })
    }, message)
    c.addCell = (name: string, data: any, message?: string) => trycall(() => nifi.api.post(`/nifi-api/process-groups/${nifi.group.id}/${name}`, data), message)
    c.setCell = (cell: Cell, data: any, message?: string) => trycall(() => nifi.api.put(`/nifi-api/${cell.prop('name')}/${cell.id}`, data), message)
    //
    c.setCellState = (cell: Cell, state: CellState) => nifi.api.put(`/nifi-api/${cell.prop('name')}/${cell.id}/run-status`, { revision: c.getCellRevision(cell), state, disconnectedNodeAcknowledged: false })
    //
    c.handleEdit = () => { }
    c.handleView = () => { }
    // modules
    c.connections = useConnections(nifi);
    c.processors = useProcessors(nifi);
    c.processGroups = useProcessGroups(nifi);
    c.blank = useBlank(nifi);
    c.funnels = useFunnels(nifi);
    c.inputPorts = useInputPorts(nifi)
    c.outputPorts = useOutputPorts(nifi)
    c.labels = useLabels(nifi)
    //
    let th:any = undefined
    // 注册事件
    nifi.graph.onMounted((graph) => {
        //
        // graph.on("render:done",() => {
        //     // pass
        //     c.connections?.done?.()
        //     c.processors?.done?.()
        //     c.processGroups?.done?.()
        //     c.blank?.done?.()
        //     c.funnels?.done?.()
        //     c.inputPorts?.done?.()
        //     // c.funnels?.done()
        //     // c.funnels?.done()
        // })
        //
        graph.on("node:dblclick",({node}) => {
            clearTimeout(th)
            const name = getCamelName(node);
            // console.log('node:dblclick-------------',name,node)
            if(name == 'processGroups'){
                c[name]?.goto(node)
            }
        })
        // 节点移动事件
        graph.on("node:moved", async ({ node }) => {
            const position = node.position();
            const sd = nifi.cells.get(node)
            if(!sd || !sd.revision) return ;
            const data = { revision: sd.revision, component: { id: node.id, position } }
            //
            try {
                const res = await c.setCell(node, data)
                const name = getCamelName(node)
                // 更新节点属性
                c[name]?.update(res)
            } catch (error) {
                ElMessage.error(t('cells-index-nodemove-failed',{error}))
                console.error(error)
            }
        })
        //
        graph.on("node:added", ({ node }) => {
            // 判断节点是否是已存在的 nifi 算子
            if (c.has(node)) {
                return;
            }
            const t = node.prop();
            const name = getCamelName(node);
            //
            const data = { name: t.label, position: t.position, type: t.type,icon:t.icon }
            // console.log('-------------',name,node,t)
            if (name) {
                c[name]?.add(data)
            }
            nifi.graph?.removeCell(node);
        })
        graph.on("blank:click",() => {
            nifi.drawer.close();
        })
        // 编辑 节点事件触发
        graph.on("cell:click", async ({ cell,e }) => {
            const name = getCamelName(cell);
            if(th){clearTimeout(th)}
            th = setTimeout(() => {
                th = undefined;
                if(c[name] && c[name].edit){
                    c[name]?.edit(cell,e)
                }
                else{
                    nifi.drawer.close();
                }
            },100)
            
        })

        // 处理组双击事件
        
        // 右键菜单事件
        graph.on("cell:contextmenu", ({ cell, e }) => {
            // nifi.graph?.resetSelection(cell);
            e.stopPropagation();
            e.preventDefault();
            const name = getCamelName(cell)
            c[name]?.contextmenu(cell,e)
        })
        // 画布右键菜单事件
        graph.on("blank:contextmenu", ({ e }) => {
            c.blank.contextmenu(e)
        })

        // 节点开关
        graph.on("node:power",({e,cell}:any) => {
            e.preventDefault();
            e.stopPropagation();
            const name = getCamelName(cell)
            console.log(cell,name)
            c[name]?.togglePower(cell)
        })

        // 节点启动
        const processorsHandle = ({e,cell}:any,state:CellState) => {
            e.preventDefault();
            e.stopPropagation();
            c.processors.changeState(cell,state)
        }
        graph.on("node:runonce",(arg:any) => {processorsHandle(arg,'RUN_ONCE')})
        graph.on("node:run",(arg:any) => {processorsHandle(arg,'RUNNING')})
        graph.on("node:stop",(arg:any) => {processorsHandle(arg,'STOPPED')})
        graph.on("node:disable",(arg:any) => {processorsHandle(arg,'DISABLED')})
        // 悬浮事件
        graph.on("node:mouseenter",({node}) => {
            const name = getCamelName(node)
            if(name == 'labels') return ;
            node.attr('body/filter',{name:"highlight",args:{blur:5,color:"rgba(0, 0, 0, 0.35)"}})            
            node.setProp('sourceZindex',node.getZIndex())
            node.setZIndex(900)
        })

        graph.on("node:mouseleave",({node}) => {
            const name = getCamelName(node)
            if(name == 'labels') return ;
            node.attr('body/filter',"")
            node.setZIndex(node.getProp('sourceZindex') || 1)
        })
        
    })

    // const refreshProp = (cell: IPackNifi.SC, data: any = {}, options: any = {}) => {
    //     if (!nifi.graph) return;
    //     const e = typeof cell == 'string' ? nifi.graph.getCellById(cell) : cell;
    //     if (!e) return;
    //     e.prop(data, options)
    // }

    // 获取元素数据
    // const get = (cell: Cell) => {
    //     const url = `/nifi-api/${cell.prop('name')}/${cell.id}`
    //     return nifi.api.get(url);
    // }
    // // 新增元素
    // const add = async (cell: Cell | string, data: any) => {
    //     const url = `/nifi-api/process-groups/${nifi.group.id}/${typeof cell == 'string' ? cell : cell.prop('name')}`
    //     try {
    //         return await nifi.api.post(url, data)
    //     } catch (error) {
    //         ElMessage.error('新增元素失败 :: ' + error);
    //         console.error(error);
    //         return false;
    //     }

    // }
    // 删除元素
    // const remove = async (cell: Cell) => {
    //     const url = `/nifi-api/${cell.prop('name')}/${cell.id}?version=${nifi.getCellData(cell.id).revision.version}`
    //     try {
    //         const res = await nifi.api.delete(url);
    //         nifi.Graph.removeCell(cell)
    //         return res;
    //     } catch (error) {
    //         ElMessage.error('删除元素失败 :: ' + error);
    //         console.error(error);
    //         return false;
    //     }

    // }
    // 更新元素数据
    // const update = (cell: Cell | string, data: any) => {
    //     const url = `/nifi-api/${typeof cell == 'string' ? cell : cell.prop('name')}/${data.component.id}`
    //     return nifi.api.put(url, data)
    // }
    // status
    // const status = async (cell:Cell,state:"RUN_ONCE" | "STOPPED" | "RUNNING" | "DISABLED" | "ENABLED") => {
    //     const name = cell.prop('name')
    //     const url = `/nifi-api/${name}/${cell.id}/run-status`;
    //     const cd = nifi.getCellData(cell)
    //     const data = { "revision": cd.revision, state: state == "ENABLED" ? "STOPPED" : state, "disconnectedNodeAcknowledged": false };
    //     //
    //     try {
    //         const res = await nifi.api.put(url,data)
    //         // @ts-ignore
    //         nifi.cellApi[camelCase(name)]?.update(res)
    //         return res;
    //     } catch (error) {
    //         ElMessage.error('更新元素状态失败 :: ' + error);
    //         console.error(error);
    //         return false;
    //     }
    // }
    // 编辑
    // const edit = async (e: string|Cell) => {
    //     //
    //     const is = typeof e === 'string';
    //     const name = is ? e : camelCase(e.prop('name'))
    //     // @ts-ignore
    //     if (nifi.cellApi[name]?.edit) {
    //         nifi.drawer.open();
    //         // @ts-ignore
    //         const vnode = await nifi.cellApi[name]?.edit(!is ? e : undefined)
    //         nifi.drawer.set(vnode)
    //     }
    // }
    // 查看
    // const view = async (e: string|Cell) => {
    //     const is = typeof e === 'string';
    //     const name = is ? e : camelCase(e.prop('name'))
    //     // @ts-ignore
    //     if (nifi.cellApi[name]?.view) {
    //         nifi.drawer.open();
    //         // @ts-ignore
    //         const vnode = await nifi.cellApi[name]?.view(!is ? e : undefined)
    //         nifi.drawer.set(vnode)
    //     }
    // }

    //
    // const connections = useConnections(nifi)
    // const processors = useProcessors(nifi)
    // const blank = useBlank(nifi)
    // const processGroups = useProcessGroups(nifi)
    // 初始化布局
    // const layout = (ces: any[]) => {


    //     return ces;
    // }

    return c as IPackNifi.Cells;

    // return {
    //     //
    //     get,
    //     add,
    //     remove,
    //     update,
    //     status,
    //     //
    //     edit,
    //     view,
    //     // select,
    //     // center,
    //     // refresh,
    //     layout,
    //     refreshProp,
    //     // contextmenu,
    //     connections,
    //     processors,
    //     labels: processors,
    //     funnels: processors,
    //     templates: processors,
    //     processGroups,
    //     inputPorts: processors,
    //     outputPorts: processors,
    //     blank

    // }
}